#include "mydriver.h"
#include "pinctrl.h"
#include "gpio.h"
#include "adc.h"
#include "adc_porting.h"

#define MAX395_PIN_DIN 13
#define MAX395_PIN_SCLK 12
#define MAX395_PIN_CS 15

#define DAC_PIN_CLK 16
#define DAC_PIN_DIN 17
#define DAC_PIN_CS 18

#define GAFE_SAMPLE_VALUE_SIGN_BIT        17
#define ADC_REFERENCE_VOLTAGE_MV          1500
#define ADC_REF_VOL_DIFFERENCE_MULT       2
#define ADC_TICK2VOL_REF_VOLTAGE_MV       (ADC_REFERENCE_VOLTAGE_MV * ADC_REF_VOL_DIFFERENCE_MULT)

void init_max395(void)
{
    uapi_pin_set_mode(MAX395_PIN_DIN, HAL_PIO_FUNC_GPIO);
    uapi_pin_set_mode(MAX395_PIN_SCLK, HAL_PIO_FUNC_GPIO);
    uapi_pin_set_mode(MAX395_PIN_CS, HAL_PIO_FUNC_GPIO);

    uapi_gpio_set_dir(MAX395_PIN_DIN, GPIO_DIRECTION_OUTPUT);
    uapi_gpio_set_dir(MAX395_PIN_SCLK, GPIO_DIRECTION_OUTPUT);
    uapi_gpio_set_dir(MAX395_PIN_CS, GPIO_DIRECTION_OUTPUT);

    uapi_gpio_set_val(MAX395_PIN_SCLK, GPIO_LEVEL_LOW);
    uapi_gpio_set_val(MAX395_PIN_CS, GPIO_LEVEL_LOW);
}

void max395_write(unsigned char data)
{
    unsigned char i;

    // uapi_gpio_set_val(MAX395_PIN_CS, GPIO_LEVEL_HIGH);
    // uapi_gpio_set_val(MAX395_PIN_CS, GPIO_LEVEL_LOW);

    for (i = 0; i < 8; i++) {
        if (data & 0x80) {
            uapi_gpio_set_val(MAX395_PIN_DIN, GPIO_LEVEL_HIGH);
        } else {
            uapi_gpio_set_val(MAX395_PIN_DIN, GPIO_LEVEL_LOW);
        }

        uapi_gpio_set_val(MAX395_PIN_SCLK, GPIO_LEVEL_HIGH);
        data <<= 1;
        uapi_gpio_set_val(MAX395_PIN_SCLK, GPIO_LEVEL_LOW);
    }

    uapi_gpio_set_val(MAX395_PIN_CS, GPIO_LEVEL_HIGH);
    uapi_gpio_set_val(MAX395_PIN_CS, GPIO_LEVEL_LOW);
}

void switch_on(unsigned char *switch_state, unsigned char n)
{
    //n = 0~4
    *switch_state |= (1 << n);
    max395_write(*switch_state);
}

void switch_off(unsigned char *switch_state, unsigned char n)
{
    //n = 0~4
    *switch_state &= ~(1 << n);
    max395_write(*switch_state);
}

void switch_all_on(unsigned char *switch_state)
{
    *switch_state |= 0x1f;
    max395_write(*switch_state);
}

void switch_all_off(unsigned char *switch_state)
{
    *switch_state &= 0xe0;
    max395_write(*switch_state);
}

void tia_on(unsigned char *switch_state, unsigned char n)
{
    //n = 0~2
    *switch_state |= (1 << (n + 5));
    max395_write(*switch_state);
}

void tia_off(unsigned char *switch_state, unsigned char n)
{
    //n = 0~2
    *switch_state &= ~(1 << (n + 5));
    max395_write(*switch_state);
}

void tia_all_on(unsigned char *switch_state)
{
    *switch_state |= 0xe0;
    max395_write(*switch_state);
}

void tia_all_off(unsigned char *switch_state)
{
    *switch_state &= 0x1f;
    max395_write(*switch_state);
}

void init_dac(void)
{
    uapi_pin_set_mode(DAC_PIN_CLK, HAL_PIO_FUNC_GPIO);
    uapi_pin_set_mode(DAC_PIN_DIN, HAL_PIO_FUNC_GPIO);
    uapi_pin_set_mode(DAC_PIN_CS, HAL_PIO_FUNC_GPIO);

    uapi_gpio_set_dir(DAC_PIN_CLK, GPIO_DIRECTION_OUTPUT);
    uapi_gpio_set_dir(DAC_PIN_DIN, GPIO_DIRECTION_OUTPUT);
    uapi_gpio_set_dir(DAC_PIN_CS, GPIO_DIRECTION_OUTPUT);

    uapi_gpio_set_val(DAC_PIN_CLK, GPIO_LEVEL_LOW);
    uapi_gpio_set_val(DAC_PIN_CS, GPIO_LEVEL_LOW);
}

void dac_set_voltage(float voltage)
{
    // voltage: 0~4095mV
    unsigned int dac_value;
    unsigned char i = 0;
	
    dac_value = (unsigned int)(65535.0 / 4095.0 * voltage);

    for (i = 16; i > 0; i--) {
        if (dac_value & 0x8000) {
            uapi_gpio_set_val(DAC_PIN_DIN, GPIO_LEVEL_HIGH);
        } else {
            uapi_gpio_set_val(DAC_PIN_DIN, GPIO_LEVEL_LOW);
        }

        uapi_gpio_set_val(DAC_PIN_CLK, GPIO_LEVEL_HIGH);
        dac_value <<= 1;
        uapi_gpio_set_val(DAC_PIN_CLK, GPIO_LEVEL_LOW);
    }

    uapi_gpio_set_val(DAC_PIN_CS, GPIO_LEVEL_HIGH);
    uapi_gpio_set_val(DAC_PIN_CS, GPIO_LEVEL_LOW);
}

void init_adc(void)
{
    uapi_adc_init(ADC_CLOCK_NONE);

    uapi_pin_set_mode(S_MGPIO2, PIN_MODE_0);
    uapi_gpio_set_dir(S_MGPIO2, GPIO_DIRECTION_INPUT);
    uapi_pin_set_pull(S_MGPIO2, PIN_PULL_NONE);
#if defined(CONFIG_PINCTRL_SUPPORT_IE)
    uapi_pin_set_ie(S_MGPIO2, PIN_IE_1);
#endif

    uapi_adc_open_channel(GADC_CHANNEL_0);  //GPIO02
    uapi_adc_power_en(AFE_GADC_MODE, true);
    adc_calibration(AFE_GADC_MODE, true, true, true);
}

int adc_get_voltage(void)
{
    int gadc_value = 0;
    gadc_value =  uapi_adc_auto_sample(GADC_CHANNEL_0);
    return (gadc_value * ADC_TICK2VOL_REF_VOLTAGE_MV) >> GAFE_SAMPLE_VALUE_SIGN_BIT;
}